package Estructuras;

import java.util.ArrayList;
import java.util.List;
/**
 * Estructura task_struct representa el bloque de control del proceso
 * pcb
 *
 */
public class Task_struct {
   private int pid;
   private short arrival_time;     //tiempo de llegada del proceso
   private short prio;             // prioridad el proceso
   private short state;            // estado del proceso
   private short resched;           // replanificar no entiendo bien
   private short policy;            // política de planificación (fifo, round robin, normal)
   private List<Integer> cpu_time;         // tiempo en cpu
   private List<Integer> io_time;          // tiempo en io
   private List<String> trace;
   private sched_entity se;        // estructuras que lleva las estadísticas
   private sched_class sc;
   
   //Constantes de estados
   final static short READY = 0;
   final static short RUNNING = 1; 
   final static short BLOCKED = 2;
   final static short TERMINATED = 4;
   // constantes politicas
   final static short NORMAL = 5;
   final static short RR = 6;
   final static short REALTIME = 7;

   public Task_struct(int pid, short at, short p, short st, short res, short pol,
           List<Integer> cpu, List<Integer> io, List<String> tra, sched_entity se, sched_class sc){
       this.pid = pid;
        this.arrival_time = at;
        this.prio = p;
        this.state = st;
        this.resched = res;
        this.policy = pol;
        this.cpu_time = new ArrayList<Integer>();
        this.cpu_time = cpu;
        this.io_time = new ArrayList<Integer>();
        this.io_time = io;
        this.trace = new ArrayList<String>();
        this.trace = tra;
        this.se = se;
        this.sc = sc;
    }


   public Task_struct(){
        this.pid = 0;
        this.arrival_time = 0;
        this.prio = 0;
        this.state = 0;
        this.resched = 0;
        this.policy = 0;
	this.cpu_time = new ArrayList<Integer>();
	this.io_time = new ArrayList<Integer>();
	this.trace = new ArrayList<String>();
        this.se = new sched_entity(0, 0, 0,0) ;
        this.sc = null;
   }

   /**
 * setpid
 * asigna pid como identificador del proceso
 * @param pid identif. del proc.
 */
    public void setPid(int pid){
        this.pid = pid;
    }
 /** getPid
 * retorna el pid del proceso
 */
    public int getPid(){
        return this.pid;
    }

/**
 * setArrivalTime
 * asigna at como tiempo de llegada
 * @param at tiempo de llegada del proceso
 */
    public void setArrivalTime(short at){
        this.arrival_time = at;
    }
    /** getArrivalTime
 * retorna el tiempo de llegada del proceso
 */
    public short getArrivalTime(){
        return this.arrival_time;
    }
 /**
 * setPrio
 * asigna p como prioridad
 * @param p prioridad del proceso
 */
    public void setPrio(short p){
        this.prio = p;
    }
 /** getPrio
 * retorna la prioridad del proceso
 */
    public short getPrio(){
        return this.prio;
    }
   /**
 * setState
 * asigna s como estado
 * @param s estado del proceso
 */
    public void setState(short s){
        this.state = s;
    }

 /** getState
 * retorna el estado del proceso
 */
    public short getState(){
        return this.state;
    }
/** setResched
 * asigna rs
 * @param rs
 */
    public void setResched(short rs){
        this.resched = rs;
    }
/** getResched
 * retorna resched
 */
    public short getResched(){
        return this.resched;
    }
/** setPolicy
 * asigna la politica de planificación del proceso
 * @param pol
 */
     public void setPolicy(short pol){
        this.policy = pol;
    }
/** getPolicy
 * retorna la politica de planificación
 */
    public short getPolicy(){
        return this.policy;
    }
/**
 * setCpuTime
 * asigna ct como tiempo en cpu
 * @param ct tiempo en cpu
 */
    public void setCputime(List<Integer> timeCpu){
        this.cpu_time = timeCpu;
    }
/** getCpuTime
 * retorna el tiempo en cpu del proceso
 */
    public int getCpuTime(){
  	if(!this.cpu_time.isEmpty()){
		int get = ((Integer)this.cpu_time.get(0)).intValue();
		return get;
	}else{
		return 0;
	}
    }
    
    public List<Integer> getCpuAll(){
  	return this.cpu_time;
	
    }
    public int disminuirCpu(){
  	if(!this.cpu_time.isEmpty()){
		int get = ((Integer)this.cpu_time.get(0)).intValue();
                this.cpu_time.remove(0);
                get--;
                if(get != 0){
                    this.cpu_time.add(0, get);
                }
                return get;              
	}else{
		return 0;
	}
    }
/**
 * setIOTime
 * asigna it como tiempo que pasa el proceso realizando entrada/salida
 * @param it tiempo en io
 */
    public void setIOtime(List<Integer> timeIo){
       	this.io_time = timeIo;
    }
 /** getIOTime
 * retorna el tiempo en io del proceso
 */
    public int getIOTime(){
       if(!this.io_time.isEmpty()){
		int get = ((Integer)this.io_time.get(0)).intValue();
		return get;
	}else{
		return 0;
	}
    }
    
    public List<Integer> getIOAll(){
  	return this.io_time;
	
    }
     public int disminuirIO(){
  	if(!this.io_time.isEmpty()){
		int get = ((Integer)this.io_time.get(0)).intValue();
                this.io_time.add(0,get-1);
		return get;
	}else{
		return 0;
	}
    }
   
   public void setTrace(List<String> tra){
        this.trace = tra;
   }
   
   public List<String> getAllTrace(){
        return this.trace;
   }
   
   public String getFirtsTrace(){
       String val = this.trace.get(0);
       this.trace.remove(0);
        return val;
   }
   
    public void setSE(sched_entity se){
        this.se = se;
    }
    public sched_entity getSE(){
        return this.se;
    }

    public void setSC(sched_class sc){
        this.sc = sc;
    }
    public sched_class getSC(){
        return this.sc;
    }


    /**
     * Método para imprimir estadisticas del proceso
     */
    public void imprimirStadistica(){
       System.out.println("  Pid:"+this.pid+" Espera antes de ejecutar "+se.getWaitToExec() + " ciclos");
    }


}
